import {DoubleSide, Mesh, MeshBasicMaterial, PlaneGeometry, Vector2} from "three";
import {PointMesh} from "./components/PointMesh.ts";
import {PointLineContainerMesh} from "./components/PointLineContainerMesh.ts";
import type {CircleItem} from "./components/CircleItem.ts";
import {StaticPointMesh} from "./components/StaticPointMesh.ts";
import {SimpleModel} from "../../framework/model/SimpleModel.ts";

export class PointsModel extends SimpleModel {

    // 两个动态格子, N个静态格子(静态区归档动态区第二个区块数据, 减少GPU资源)

    dynamic0!: PointMesh
    dynamic1!: PointLineContainerMesh

    staticArr: StaticPointMesh[]

    width!: number
    heightUnit!: number
    count!: number

    dynamicCnt!: number
    staticCnt!: number

    baseGeo!: PlaneGeometry
    baseMat!: MeshBasicMaterial

    threshold!: number
    filterThreshold!: number

    backgroundColor: number

    constructor() {
        super("PointsModel")
        this.staticArr = []
        this.backgroundColor = 0x78b1e5
        // this.backgroundColor = 0x
    }

    /**
     * 初始化, 创建一个背景, 创建2个dynamic展示区, 创建count-2个静态区(静态区延迟创建)
     * @param width 宽度
     * @param heightUnit 单位数据块的高度
     * @param count 数据块总数 > 2
     */
    init(width: number, heightUnit: number, count: number) {
        this.threshold = 0.5
        this.filterThreshold = 0.1
        this.width = width
        this.heightUnit = heightUnit
        this.count = count
        this.dynamicCnt = 2
        this.staticCnt = this.count - this.dynamicCnt
        if (count < 2) {
            console.error("Points模型的card数量必须大于2")
            return
        }
        this.genBasePlane()
        this.genDynamicCard()
    }

    setThreshold(alarmThreshold: number, skipThreshold: number) {
        this.threshold = alarmThreshold
        this.filterThreshold = skipThreshold
    }

    genBasePlane() {
        let height = this.heightUnit*this.count + 5
        let width = this.width + 5
        this.baseGeo = new PlaneGeometry(width, height, width-1, height-1)
        this.baseMat = new MeshBasicMaterial({
            color: this.backgroundColor,
            side: DoubleSide
        })
        let baseMesh = new Mesh(this.baseGeo, this.baseMat)
        this.scene?.add(baseMesh)
    }

    genDynamicCard() {
        // d0
        let card0 = new PointMesh(this.width, this.heightUnit)
        let card0Pos = this.calcCardPosition(0)
        // console.log("card0 pos", card0Pos)
        card0.position.set(card0Pos.x, card0Pos.y, 0.005)
        // d1
        let card1 = new PointLineContainerMesh(this.width, this.heightUnit)
        let card1Pos = this.calcCardPosition(1)
        // console.log("card1 pos", card1Pos)
        card1.position.set(card1Pos.x, card1Pos.y, 0.005)
        // card1.position.setZ(0.005)
        this.dynamic0 = card0
        this.dynamic1 = card1
        this.scene?.add(card0)
        this.scene?.add(card1)

        this.dynamic0.onFull((arr: Mesh[][]) => {
            for (let i = 0; i < arr.length; i++) {
                let line = arr[i]
                this.dynamic1.addCircleLine(line)
                this.moveUpStaticCards(arr.length)
            }
        })
        this.dynamic1.onFull = (arr: Mesh[]) => {
            this.genS0(arr)
        }
    }

    addLine(circles: [number, number][]) {
        if (circles.length === 0) { // 添加空白行
            this.dynamic0.addCircleLine([])
            return
        }
        let circleItems: CircleItem[] = []
        for (let i = 0; i < circles.length; i++) {
            let circle = circles[i]
            let x = circle[0]
            let radius = circle[1]
            if (radius < this.filterThreshold) {
                return
            }
            let category = 1
            if (radius > this.threshold) {
                category = 9
            }
            circleItems.push({x: x, radius: 0.4, category: category})
        }
        this.dynamic0.addCircleLine(circleItems)
    }

    genS0(arr: Mesh[]) {
        // console.log('创建static card')
        let staticCard = new StaticPointMesh(this.width, this.heightUnit)
        staticCard.addMesh(arr)

        let pos = this.calcCardPosition(1)
        // console.log("static1 pos", pos)
        staticCard.position.set(pos.x, pos.y, 0.007)
        this.scene?.add(staticCard)
        this.staticArr.push(staticCard)

        let overflow = this.staticArr.length - this.staticCnt
        if (overflow>0) {
            for (let i = 0; i < overflow; i++) {
                let card = this.staticArr.shift()
                if (!card) {
                    continue
                }
                this.scene?.remove(card)
                card.disposeAll()
            }
        }
    }

    moveUpStaticCards(lines: number) {
        // 上移一行
        for (let i = 0; i < this.staticArr.length; i++) {
            let card = this.staticArr[i]
            card.position.setY(card.position.y+lines)
        }
    }

    calcCardPosition(index: number): Vector2 {
        let heightBottom = -this.heightUnit*(this.count) / 2
        let y = this.heightUnit*(index+ 1/2) + heightBottom
        return new Vector2(0, y)
    }
}
